import fetch from 'node-fetch';
import { createLogger } from "./Logger.js";
import process from "process";

export class SonarQubeClient {
    constructor() {
        this.baseUrl = 'https://sonarqube.hszq8.com';
        this.verbose = process.env.VERBOSE;
        this.logger = createLogger("SonarQube");
        this.cookies = new Map(); // 存储 cookies
        this.xsrfToken = null;
        this.jwtSession = null;
    }

    /**
     * 解析并存储 Set-Cookie 响应头
     * @param {Headers} headers 响应头
     */
    parseCookies(headers) {
        const setCookieHeader = headers.get('set-cookie');
        if (setCookieHeader) {
            const cookies = setCookieHeader.split(',').map(cookie => cookie.trim());
            cookies.forEach(cookie => {
                const [nameValue] = cookie.split(';');
                const [name, value] = nameValue.split('=');
                if (name && value) {
                    this.cookies.set(name.trim(), value.trim());

                    // 特殊处理 XSRF-TOKEN 和 JWT-SESSION
                    if (name.trim() === 'XSRF-TOKEN') {
                        this.xsrfToken = value.trim();
                    } else if (name.trim() === 'JWT-SESSION') {
                        this.jwtSession = value.trim();
                    }
                }
            });
        }
    }

    /**
     * 生成 Cookie 字符串
     * @returns {string}
     */
    getCookieString() {
        const cookieArray = [];
        // 添加固定的 GA cookies
        cookieArray.push('_ga=GA1.1.1788617569.1747661917');
        cookieArray.push('*ga*89WN60ZK2E=GS2.1.s1747661917$o1$g1$t1747662958$j0$l0$h0');

        // 添加动态 cookies
        for (const [name, value] of this.cookies) {
            cookieArray.push(`${name}=${value}`);
        }

        return cookieArray.join('; ');
    }

    /**
     * 通用请求方法
     * @param {string} pathOrUrl API 路径或完整 URL
     * @param {string} method 请求方法
     * @param {object|string|null} body 请求体
     * @param {object} additionalHeaders 额外的请求头
     * @returns {Promise<any>}
     */
    async request(pathOrUrl, method = 'GET', body = null, additionalHeaders = {}) {
        const url = pathOrUrl.startsWith('http') ? pathOrUrl : `${this.baseUrl}${pathOrUrl}`;

        const headers = {
            'Accept': 'application/json',
            'Accept-Language': 'zh-CN,zh;q=0.9',
            'Origin': this.baseUrl,
            'Priority': 'u=1, i',
            'Referer': `${this.baseUrl}/`,
            'Sec-CH-UA': '"Chromium";v="140", "Not=A?Brand";v="24", "Google Chrome";v="140"',
            'Sec-CH-UA-Mobile': '?0',
            'Sec-CH-UA-Platform': '"macOS"',
            'Sec-Fetch-Dest': 'empty',
            'Sec-Fetch-Mode': 'cors',
            'Sec-Fetch-Site': 'same-origin',
            'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36',
            'Cookie': this.getCookieString(),
            ...additionalHeaders
        };

        // 如果有 XSRF token，添加到请求头
        if (this.xsrfToken) {
            headers['X-XSRF-Token'] = this.xsrfToken;
        }

        const options = {
            method,
            headers,
        };

        if (body) {
            if (typeof body === 'string') {
                options.body = body;
            } else {
                options.headers['Content-Type'] = 'application/json';
                options.body = JSON.stringify(body);
            }
        }

        if (this.verbose) {
            this.logger.info(
                `➡️ 请求:\n url=${url}\n method=${method}\n headers=${JSON.stringify(options.headers, null, 2)}\n body=${options.body || '{}'}`
            );
        }

        const res = await fetch(url, options);

        // 解析响应中的 cookies
        this.parseCookies(res.headers);

        const resText = await res.text();
        let resData;
        try {
            resData = JSON.parse(resText);
        } catch {
            resData = resText;
        }

        if (this.verbose) {
            this.logger.info(
                `⬅️ 响应:\n url=${url}\n status=${res.status}\n body=${JSON.stringify(resData, null, 2)}`
            );
        }

        if (!res.ok) {
            this.logger.log(
                `请求地址 url=${url} method=${method}\n ➡️ 请求: headers=${JSON.stringify(options.headers, null, 2)}\n body=${options.body || '{}'}  ⬅️ 响应:\n \n status=${res.status}\n body=${JSON.stringify(resData, null, 2)}`
            );
            throw new Error(`请求失败，状态码 ${res.status}: ${resText}`);
        }
        return resData;
    }

    /**
     * 登录到 SonarQube
     * @param {string} username 用户名
     * @param {string} password 密码
     * @returns {Promise<any>}
     */
    async login(username, password) {
        const loginData = new URLSearchParams({
            login: username,
            password: password
        }).toString();

        const headers = {
            'Content-Type': 'application/x-www-form-urlencoded',
            'Referer': `${this.baseUrl}/sessions/new?return_to=%2F`
        };

        const result = await this.request('/api/authentication/login', 'POST', loginData, headers);

        if (this.verbose) {
            this.logger.info('✅ 登录成功');
        }

        return result;
    }

    /**
     * 获取组件度量数据（单测覆盖率、bug 情况等）
     * @param {string} componentKey 组件键值
     * @param {string[]} metricKeys 度量指标键值数组，如果不提供则使用默认的全套指标
     * @returns {Promise<any>}
     */
    async getComponentMeasures(componentKey, metricKeys = null) {
        const defaultMetrics = [
            'alert_status', 'quality_gate_details', 'bugs', 'new_bugs',
            'reliability_rating', 'new_reliability_rating', 'vulnerabilities',
            'new_vulnerabilities', 'security_rating', 'new_security_rating',
            'security_hotspots', 'new_security_hotspots', 'security_hotspots_reviewed',
            'new_security_hotspots_reviewed', 'security_review_rating',
            'new_security_review_rating', 'code_smells', 'new_code_smells',
            'sqale_rating', 'new_maintainability_rating', 'sqale_index',
            'new_technical_debt', 'coverage', 'new_coverage', 'lines_to_cover',
            'new_lines_to_cover', 'tests', 'duplicated_lines_density',
            'new_duplicated_lines_density', 'duplicated_blocks', 'ncloc',
            'ncloc_language_distribution', 'projects', 'lines', 'new_lines'
        ];

        const metrics = metricKeys || defaultMetrics;
        const params = new URLSearchParams({
            additionalFields: 'period,metrics',
            component: componentKey,
            metricKeys: metrics.join(',')
        });

        const headers = {
            'Referer': `${this.baseUrl}/dashboard?id=${componentKey}`
        };

        return await this.request(`/api/measures/component?${params.toString()}`, 'GET', null, headers);
    }

    /**
     * 获取项目的质量门禁状态
     * @param {string} componentKey 组件键值
     * @returns {Promise<any>}
     */
    async getQualityGateStatus(componentKey) {
        return await this.getComponentMeasures(componentKey, ['alert_status', 'quality_gate_details']);
    }

    /**
     * 获取项目的代码覆盖率（使用完整的指标列表）
     * @param {string} componentKey 组件键值
     * @returns {Promise<any>}
     */
    async getCoverageMetrics(componentKey) {
        // 直接使用 Java 代码中的完整 URL 参数字符串，避免编码问题
        const metricKeysParam = 'new_technical_debt%2Cblocker_violations%2Cbugs%2Cburned_budget%2Cbusiness_value%2Cclasses%2Ccode_smells%2Ccognitive_complexity%2Ccomment_lines%2Ccomment_lines_density%2Cbranch_coverage%2Cnew_branch_coverage%2Cconditions_to_cover%2Cnew_conditions_to_cover%2Cconfirmed_issues%2Ccoverage%2Cnew_coverage%2Ccritical_violations%2Ccomplexity%2Cdirectories%2Cduplicated_blocks%2Cnew_duplicated_blocks%2Cduplicated_files%2Cduplicated_lines%2Cduplicated_lines_density%2Cnew_duplicated_lines_density%2Cnew_duplicated_lines%2Ceffort_to_reach_maintainability_rating_a%2Cfalse_positive_issues%2Cfiles%2Cfunctions%2Cgenerated_lines%2Cgenerated_ncloc%2Cinfo_violations%2Cviolations%2Cline_coverage%2Cnew_line_coverage%2Clines%2Cncloc%2Clines_to_cover%2Cnew_lines_to_cover%2Csqale_rating%2Cnew_maintainability_rating%2Cmajor_violations%2Cminor_violations%2Cnew_blocker_violations%2Cnew_bugs%2Cnew_code_smells%2Cnew_critical_violations%2Cnew_info_violations%2Cnew_violations%2Cnew_lines%2Cnew_major_violations%2Cnew_minor_violations%2Cnew_security_hotspots%2Cnew_vulnerabilities%2Copen_issues%2Cprojects%2Calert_status%2Creliability_rating%2Cnew_reliability_rating%2Creliability_remediation_effort%2Cnew_reliability_remediation_effort%2Creopened_issues%2Csecurity_hotspots%2Csecurity_hotspots_reviewed%2Cnew_security_hotspots_reviewed%2Csecurity_rating%2Cnew_security_rating%2Csecurity_remediation_effort%2Cnew_security_remediation_effort%2Csecurity_review_rating%2Cnew_security_review_rating%2Cskipped_tests%2Cstatements%2Cteam_size%2Csqale_index%2Csqale_debt_ratio%2Cnew_sqale_debt_ratio%2Cuncovered_conditions%2Cnew_uncovered_conditions%2Cuncovered_lines%2Cnew_uncovered_lines%2Ctest_execution_time%2Ctest_errors%2Ctest_failures%2Ctests%2Ctest_success_density%2Cvulnerabilities%2Cwont_fix_issues';

        const url = `/api/measures/component?additionalFields=period&component=${componentKey}&metricKeys=${metricKeysParam}`;

        const headers = {
            'Referer': `${this.baseUrl}/dashboard?id=${componentKey}`
        };

        return await this.request(url, 'GET', null, headers);
    }

    /**
     * 获取覆盖率历史数据（默认近30天，最多返回 limit 个点）
     * @param {string} componentKey
     * @param {number} days 时间范围天数
     * @param {number} limit 返回的最多数据点数
     * @returns {Promise<Array<{date: string, value: number}>>}
     */
    async getCoverageHistory(componentKey, days = 30, limit = 15) {
        const now = new Date();
        const fromDate = new Date(now);
        fromDate.setDate(now.getDate() - days);

        const formatDate = (date) => date.toISOString().slice(0, 10); // YYYY-MM-DD

        const params = new URLSearchParams({
            component: componentKey,
            metrics: 'coverage',
            from: formatDate(fromDate),
            to: formatDate(now),
            p: '1',
            ps: '500'
        });

        const headers = {
            'Referer': `${this.baseUrl}/component_measures?id=${componentKey}&metric=coverage&view=history`
        };

        const data = await this.request(`/api/measures/search_history?${params.toString()}`, 'GET', null, headers);

        const history = (data && data.measures && data.measures[0] && Array.isArray(data.measures[0].history))
            ? data.measures[0].history
            : [];

        const normalized = history
            .map(item => ({
                date: item.date,
                value: item.value != null ? parseFloat(item.value) : NaN
            }))
            .filter(item => item.date && Number.isFinite(item.value))
            .sort((a, b) => new Date(a.date) - new Date(b.date));

        if (normalized.length > limit) {
            return normalized.slice(-limit);
        }
        return normalized;
    }

    /**
     * 构建覆盖率信息（对应 Java 版本的 buildCoverage 方法）
     * @param {string} componentKey 组件键值
     * @returns {Promise<object>} 包含覆盖率、可覆盖行、未覆盖行的对象
     */
    async buildCoverage(componentKey) {
        const data = await this.getCoverageMetrics(componentKey);

        if (!data || !data.component || !data.component.measures) {
            throw new Error(`无法获取 ${componentKey} 的覆盖率数据`);
        }

        const measures = data.component.measures;
        let coverage = '';
        let linesCover = '';
        let uncoveredLines = '';

        measures.forEach(measure => {
            switch (measure.metric) {
                case 'coverage':
                    coverage = measure.value || '';
                    break;
                case 'lines_to_cover':
                    linesCover = measure.value || '';
                    break;
                case 'uncovered_lines':
                    uncoveredLines = measure.value || '';
                    break;
            }
        });

        this.logger.log(`${componentKey} 覆盖率:${coverage},可覆盖行：${linesCover},未覆盖行:${uncoveredLines}`);

        return {
            appName: componentKey,
            coverage: coverage ? parseFloat(coverage) : 0,
            linesCover: linesCover ? parseInt(linesCover) : 0,
            uncoveredLines: uncoveredLines ? parseInt(uncoveredLines) : 0
        };
    }

    /**
     * 获取项目的代码异味信息（重点关注新代码）
     * @param {string} componentKey 组件键值
     * @returns {Promise<any>}
     */
    async getCodeSmellMetrics(componentKey) {
        return await this.getComponentMeasures(componentKey, [
            'new_code_smells', 'new_maintainability_rating', 'new_technical_debt',
            'code_smells', 'sqale_rating', 'sqale_index'
        ]);
    }

    /**
     * 格式化度量数据以便于阅读
     * @param {object} measuresData 度量数据
     * @returns {object} 格式化后的数据
     */
    formatMeasures(measuresData) {
        if (!measuresData || !measuresData.component || !measuresData.component.measures) {
            return {};
        }

        const measures = {};
        measuresData.component.measures.forEach(measure => {
            measures[measure.metric] = {
                value: measure.value,
                bestValue: measure.bestValue || false
            };
            if (measure.period) {
                measures[measure.metric].periodValue = measure.period.value;
            }
        });

        return {
            component: measuresData.component.key,
            measures
        };
    }
    /**
     * 获取单个指标数据（简单版本）
     * @param {string} componentKey 组件键值
     * @param {string} metricKey 单个指标键值，如 'coverage'
     * @returns {Promise<any>}
     */
    async getSingleMetric(componentKey, metricKey) {
        const url = `/api/measures/component?component=${componentKey}&metricKeys=${metricKey}`;

        const headers = {
            'Referer': `${this.baseUrl}/component_measures?id=${componentKey}&metric=${metricKey}&view=list`
        };

        return await this.request(url, 'GET', null, headers);
    }

    /**
     * 获取简单覆盖率数据（只获取覆盖率百分比）
     * @param {string} componentKey 组件键值
     * @returns {Promise<object>} 包含覆盖率百分比的对象
     */
    async getSimpleCoverage(componentKey) {
        const data = await this.getSingleMetric(componentKey, 'coverage');

        if (!data || !data.component || !data.component.measures || data.component.measures.length === 0) {
            throw new Error(`无法获取 ${componentKey} 的覆盖率数据`);
        }

        const coverageValue = data.component.measures[0].value;

        if (this.verbose) {
            this.logger.info(`${componentKey} 覆盖率: ${coverageValue}%`);
        }

        return coverageValue ? parseFloat(coverageValue) : 0;
    }


    /**
     * 获取最近一次分析时间与版本（打包分支）
     * @param {string} componentKey 组件键值
     * @returns {Promise<{version: string, analysisDate: string} | object>}
     */
    async getComponentNavigation(componentKey) {
        const params = new URLSearchParams({ component: componentKey });

        const headers = {
            'Referer': `${this.baseUrl}/dashboard?id=${componentKey}`
        };

        return await this.request(`/api/navigation/component?${params.toString()}`, 'GET', null, headers);
    }



    /**
     * 打印简单覆盖率报告（只显示覆盖率百分比）
     * @param {string} componentKey 组件键值
     */
    async printSimpleCoverageReport(componentKey) {
        try {
            const coverage = await this.getSimpleCoverage(componentKey);

            console.log(`\n📊 ${componentKey} 简单覆盖率报告`);
            console.log('='.repeat(30));
            console.log(`📈 覆盖率: ${coverage}%`);
            console.log('='.repeat(30));

            return coverage;
        } catch (error) {
            this.logger.error(`生成简单覆盖率报告失败: ${error.message}`);
            throw error;
        }
    }
    /**
     * 打印覆盖率报告（简化版本，只显示三个关键指标）
     * @param {string} componentKey 组件键值
     */
    async printCoverageReport(componentKey) {
        try {
            const coverageData = await this.buildCoverage(componentKey);

            console.log(`\n📊 ${componentKey} 覆盖率报告`);
            console.log('='.repeat(40));
            console.log(`📈 覆盖率: ${coverageData.coverage}%`);
            console.log(`📝 可覆盖行: ${coverageData.linesCover}`);
            console.log(`❌ 未覆盖行: ${coverageData.uncoveredLines}`);
            console.log('='.repeat(40));

            return coverageData;
        } catch (error) {
            this.logger.error(`生成覆盖率报告失败: ${error.message}`);
            throw error;
        }
    }
    /**
     * 获取组件树（文件列表）及度量数据
     * @param {string} componentKey 组件键值
     * @param {string[]} metricKeys 度量指标键值数组
     * @returns {Promise<any>}
     */
    async getComponentTree(componentKey, metricKeys) {
        const params = new URLSearchParams({
            component: componentKey,
            metricKeys: metricKeys.join(','),
            qualifiers: 'FIL', // 只获取文件
            strategy: 'all',
            ps: 500 // 分页大小，默认500
        });

        const headers = {
            'Referer': `${this.baseUrl}/component_measures?id=${componentKey}`
        };

        return await this.request(`/api/measures/component_tree?${params.toString()}`, 'GET', null, headers);
    }

    /**
     * 获取项目最新版本
     * @param {string} componentKey 组件键值
     * @returns {Promise<string>}
     */
    async getProjectVersion(componentKey) {
        try {
            const params = new URLSearchParams({
                project: componentKey,
                ps: 1 // 只需要最新的一条
            });
            const data = await this.request(`/api/project_analyses/search?${params.toString()}`, 'GET');
            if (data && data.analyses && data.analyses.length > 0) {
                return data.analyses[0].projectVersion || '-';
            }
            return '-';
        } catch (e) {
            this.logger.warn(`获取版本信息失败: ${e.message}`);
            return '-';
        }
    }
}
export async function getSimpleCoverage(appName) {

}

